﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Text;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using UnityEngine.UI;
using Newtonsoft.Json;

// S2C message: after login
class MessageLoginResponse {
	public string success;
	public string message;
	public string token;
};

// S2C message: after autologin
class MessageAutoLoginResponse {
	public string success;
	public string message;
};

public class NetworkManager : SingletonBehaviour<NetworkManager> {

	//we implement 2 instances : http & https in different port, and test them all passed.
	readonly string httpRegisterUrl = "http://101.132.70.210:8081/api/register";
	readonly string httpsRegisterUrl = "https://101.132.70.210:8443/api/register";

	readonly string httpsLoginUrl = "https://101.132.70.210:8443/api/login";
	readonly string httpsAutoLoginUrl = "https://101.132.70.210:8443/api/autologin";

	readonly string nitUserNameKey = "nitUserName";
	readonly string nitUserTokenKey = "nitUserToken";

	Text passwordText;
	InputField nameText;

	void Awake() {
		
	}

	void Start() {
		Debug.Log ("NetworkStart Manager.");

		//注册按钮
		Button register = GameObject.FindGameObjectWithTag("RegisterButton").GetComponent<Button>();
		register.onClick.AddListener (Register);

		//登录按钮
		Button login = GameObject.FindGameObjectWithTag("LoginButton").GetComponent<Button>();
		login.onClick.AddListener (Login);

		//名字控件
		nameText = GameObject.Find("Canvas/UserName").GetComponent<InputField>();

		//密码控件
		passwordText = GameObject.Find("Canvas/Password/Text").GetComponent<Text>();

		//查看是否有用户名和token的存在
		string userName = PlayerPrefs.GetString(nitUserNameKey);
		string userToken = PlayerPrefs.GetString (nitUserTokenKey);
		if (userName != "" && userToken != "") {
			//隐藏注册按钮
			register.gameObject.SetActive (false);
			//隐藏密码输入框
			passwordText.transform.parent.gameObject.SetActive (false);
			GameObject.Find ("Canvas/Text (1)").gameObject.SetActive (false);
			//隐藏自动登录开关
			GameObject.Find ("Canvas/Toggle").gameObject.SetActive (false);
			//用储存的用户名填充登录名栏位
			nameText.text = userName;

			//登录方法用自动登录
			login.onClick.RemoveListener(Login);
			login.onClick.AddListener (AutoLogin);
		}
	}

	public void Register() {

		ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

		//1、request
		WebRequest request = WebRequest.Create (httpsRegisterUrl);
		request.Method = "POST";

		var parms = new Dictionary<string, string> ();
		parms.Add ("name", nameText.text);
		parms.Add ("password", passwordText.text);

		string postData = DictToString (parms);

		byte[] byteArray = Encoding.UTF8.GetBytes (postData);
		request.ContentType = "application/x-www-form-urlencoded";
		request.ContentLength = byteArray.Length;

		Stream dataStream = request.GetRequestStream();
		dataStream.Write (byteArray, 0, byteArray.Length);
		dataStream.Close ();

		//2、response
		WebResponse response = request.GetResponse();
		Debug.Log (((HttpWebResponse)response).StatusDescription);

		dataStream = response.GetResponseStream ();
		StreamReader reader = new StreamReader (dataStream);
		string responseFromServer = reader.ReadToEnd ();
		Debug.Log (responseFromServer);

		reader.Close ();
		dataStream.Close ();
		response.Close ();		
	}

	public void Login() {
		ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

		//1、request
		WebRequest request = WebRequest.Create (httpsLoginUrl);
		request.Method = "POST";

		var parms = new Dictionary<string, string> ();
		parms.Add ("name", nameText.text);
		parms.Add ("password", passwordText.text);

		string postData = DictToString (parms);

		byte[] byteArray = Encoding.UTF8.GetBytes (postData);
		request.ContentType = "application/x-www-form-urlencoded";
		request.ContentLength = byteArray.Length;

		Stream dataStream = request.GetRequestStream();
		dataStream.Write (byteArray, 0, byteArray.Length);
		dataStream.Close ();

		//2、response
		WebResponse response = request.GetResponse();
		Debug.Log (((HttpWebResponse)response).StatusDescription);

		dataStream = response.GetResponseStream ();
		StreamReader reader = new StreamReader (dataStream);
		string responseFromServer = reader.ReadToEnd ();
		Debug.Log (responseFromServer);

		MessageLoginResponse result = JsonConvert.DeserializeObject<MessageLoginResponse>(responseFromServer);
		if (result.success == "true" && result.token != "") {
			PlayerPrefs.SetString (nitUserNameKey, nameText.text);
			PlayerPrefs.SetString (nitUserTokenKey, result.token);
			PlayerPrefs.Save ();
		}



		reader.Close ();
		dataStream.Close ();
		response.Close ();		
	}

	public void AutoLogin() {
		ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

		//1、request
		WebRequest request = WebRequest.Create (httpsAutoLoginUrl);
		request.Method = "POST";

		var parms = new Dictionary<string, string> ();
		parms.Add ("name", nameText.text);
		parms.Add ("token", PlayerPrefs.GetString (nitUserTokenKey));

		string postData = DictToString (parms);

		byte[] byteArray = Encoding.UTF8.GetBytes (postData);
		request.ContentType = "application/x-www-form-urlencoded";
		request.ContentLength = byteArray.Length;

		Stream dataStream = request.GetRequestStream();
		dataStream.Write (byteArray, 0, byteArray.Length);
		dataStream.Close ();

		//2、response
		WebResponse response = request.GetResponse();
		Debug.Log (((HttpWebResponse)response).StatusDescription);

		dataStream = response.GetResponseStream ();
		StreamReader reader = new StreamReader (dataStream);
		string responseFromServer = reader.ReadToEnd ();
		Debug.Log (responseFromServer);

		MessageAutoLoginResponse result = JsonConvert.DeserializeObject<MessageAutoLoginResponse>(responseFromServer);
		Debug.Log (result.success + " | " + result.message);

		reader.Close ();
		dataStream.Close ();
		response.Close ();		
	}

	string DictToString(Dictionary<string, string> dict) {
		StringBuilder builder = new StringBuilder ();

		foreach (KeyValuePair<string, string> kvp in dict) {
			builder.Append (kvp.Key + "=" + kvp.Value + "&");
		}

		return builder.ToString ();
	}

	public bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
		bool isOk = true;
		// If there are errors in the certificate chain, look at each error to determine the cause.
		if (sslPolicyErrors != SslPolicyErrors.None) {
			for (int i=0; i<chain.ChainStatus.Length; i++) {
				if (chain.ChainStatus [i].Status != X509ChainStatusFlags.RevocationStatusUnknown) {
					chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
					chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
					chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (0, 1, 0);
					chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
					bool chainIsValid = chain.Build ((X509Certificate2)certificate);
					if (!chainIsValid) {
						isOk = false;
					}
				}
			}
		}
		return isOk;
	}
}

